package com.netty.handler;

import com.netty.CIMWebSocketRequestHandler;
import com.netty.constant.Constants;
import com.netty.model.SentBody;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.handler.timeout.IdleState;
import io.netty.handler.timeout.IdleStateEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Objects;

/**
 * @Title: HeartBeatServerHandler
 * @Author zl
 * @Package com.netty.handler
 * @Date 2025/1/14 13:14
 * @description: 心跳检测
 */

public class HeartBeatServerHandler extends SimpleChannelInboundHandler<SentBody> {

    private static final Logger logger = LoggerFactory.getLogger(ChannelInboundHandlerAdapter.class);

    private ChannelGroup channelGroup;

    public HeartBeatServerHandler( ChannelGroup channelGroup) {
        this.channelGroup = channelGroup;
    }


    @Override
    protected void channelRead0(ChannelHandlerContext ctx, SentBody sentBody) throws Exception {
        if(sentBody.getType() == Constants.CmdType.ONLINE){
            SentBody message = new SentBody();
            ctx.channel().attr(Constants.SessionConfig.UID).set(sentBody.getKey());
            message.setType(Constants.CmdType.MESSAGE);
            if(Objects.nonNull(channelGroup)){
                channelGroup.add(ctx.channel());
            }
            ctx.channel().writeAndFlush(message);
            return;
        }
        ctx.fireChannelRead(sentBody);

    }


    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) {
        if (!(evt instanceof IdleStateEvent)) {
            return;
        }

        IdleStateEvent idleEvent = (IdleStateEvent) evt;

        String uid = ctx.channel().attr(Constants.SessionConfig.UID).get();

        /*
         * 关闭未认证的连接
         */
        if (idleEvent.state() == IdleState.WRITER_IDLE && uid == null) {
            ctx.close();
            return;
        }

        /*
         * 已经认证的连接发送心跳请求
         */
        if (idleEvent.state() == IdleState.WRITER_IDLE && uid != null) {
            Integer pingCount = ctx.channel().attr(Constants.SessionConfig.PING_COUNT).get();
            logger.info("===============心跳检测("+pingCount+")===============");
            ctx.channel().attr(Constants.SessionConfig.PING_COUNT).set(pingCount == null ? 1 : pingCount + 1);
            SentBody sentBody = new SentBody();
            sentBody.setType(Constants.CmdType.PONG);
            ctx.channel().writeAndFlush(sentBody);
            return;
        }
        /*
         * 如果心跳请求发出30秒内没收到响应，则关闭连接
         */
        Integer pingCount = ctx.channel().attr(Constants.SessionConfig.PING_COUNT).get();
        if (idleEvent.state() == IdleState.READER_IDLE && pingCount != null && pingCount >= Constants.ImserverConfig.PING_TIME_OUT) {
            ctx.close();
            logger.info("{} pong timeout.", ctx.channel());
        }

    }

}
